﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Bluyel.Core
{
    /// <summary>
    /// Represents a unique identifier.
    /// hide the implementation of the Guid.
    /// 
    /// When an id is set, its unmutable, unable to change the internal Guid.
    /// </summary>
    public class UniqueId
    {
        /// <summary>
        /// the concrete id implementation.
        /// </summary>
        private Guid _id;
        
        //---------------------------------------------------------------------
        /// <summary>
        /// Create a new entityId, provide the guid.
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public static UniqueId Create(string guid)
        {
            UniqueId id = new UniqueId(false);
            if (id.SetFromIdStr(guid))
                return id;

            return null;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Check the id, if not null, if set correctly.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static bool Check(UniqueId id)
        {
            if (id == null)
                return false;

            return id.CheckInternal();
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// The default Constructor, generate a new Id.
        /// </summary>
        public UniqueId()
        {
            GenerateId();
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Constructor, generate an id now if true.
        /// </summary>
        /// <param name="generateIdNow"></param>
        public UniqueId(bool generateIdNow)
        {
            if (generateIdNow)
                GenerateId();
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Constructor, provide the guid.
        /// </summary>
        /// <param name="generateIdNow"></param>
        public UniqueId(string guid)
        {
            SetFromIdStr(guid);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Check the id, if null or empty, its a wrong id.
        /// </summary>
        /// <returns></returns>
        public bool CheckInternal()
        {
            if (_id == null)
                return false;

            if (_id == Guid.Empty)
                return false;

            // check the internal GUID/UUID
            // todo:  possible?                  _id = new Guid(idStr);  dans un try/catch


            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Generate a new id, only if not yet set.
        /// </summary>
        /// <returns></returns>
        public bool GenerateId()
        {
            if (_id != Guid.Empty)
                return false;

            _id = Guid.NewGuid();
            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Build a id from a string id format.
        /// return true if ok, false if the id is already set or the provided string id is wrong. 
        ///
        /// </summary>
        /// <param name="idStr"></param>
        /// <returns></returns>
        public bool SetFromIdStr(string idStr)
        {
            try
            {
                if (_id != Guid.Empty)
                    return false;

                _id = new Guid(idStr);
                return true;
            }
            catch //(Exception e)
            {
                // error, the id is not set, equals null
                _id = Guid.Empty;
                return false;
            }
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Return true if the provided id is equal to the inner id.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool IdAreEquals(UniqueId id)
        {
            if (id == null)
                return false;

            if (id._id.Equals(this._id))
                return true;

            return false;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Return true if the provided id is equal to the inner id.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool IdAreEquals(string idStr)
        {
            if (string.IsNullOrWhiteSpace(idStr))
                return false;

            UniqueId id = new UniqueId(idStr);

            return this.IdAreEquals(id);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// If the guid is not set (is set to 0)
        /// return '(null)'
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            if (_id == Guid.Empty)
                return "(null)";

            return _id.ToString();
        }
    }
}
